package ar.uba.fi.algo3.algoTank;

import java.io.Serializable;

import ar.uba.fi.algo3.algoTank.Excepciones.JuegoGanadoException;
import ar.uba.fi.algo3.algoTank.Excepciones.JuegoPerdidoException;
import ar.uba.fi.algo3.algoTank.Objetos.Base;
import ar.uba.fi.algo3.algoTank.Objetos.Territorio;
import ar.uba.fi.algo3.algoTank.Objetos.Tanques.AlgoTank;

public class Juego implements Serializable {
	
	private static final long serialVersionUID = 4L;
	
	private transient Territorio territorio;
	private AlgoTank jugador;
	private Base base;
	private AdministradorNivel administradorNivel;
	private int nivelMaximo;
	private transient CreadorDeFlotas creadorFlotas;
	private transient CreadorDeItems creadorItems;
	private Flota flotaActual;
	private int contadorDeCiclos;
	private boolean pausa;
	
	
	public Juego() {
		
		this.nivelMaximo = 2;
		this.contadorDeCiclos = 0;
		this.territorio = new Territorio();
		this.jugador = new AlgoTank();
		this.base = new Base();
		this.creadorFlotas = new CreadorDeFlotas(territorio,jugador,base);
		this.creadorItems = new CreadorDeItems(territorio);
		pausa=false;
		administradorNivel = new AdministradorNivel(this);
		jugador.setTerritorio(territorio);
		base.setTerritorio(territorio);
	}
	
	public AlgoTank getJugador() {
		return jugador;
	}
	
	
	public AdministradorNivel getAdministradorNivel(){
		return this.administradorNivel;
	}
	
	public Territorio getTerritorio(){
		return territorio;
	}
	
	public void setNivelMaximo(int nivelMaximo){
		this.nivelMaximo = nivelMaximo;
	}
	
	public void subirNivel() throws JuegoGanadoException {
		administradorNivel.subirNivel(); 
		if (administradorNivel.getNivelActual() > nivelMaximo)
			throw new JuegoGanadoException();
		else{
			 this.territorio.deleteAllObjetos();
			 administradorNivel.setNivel();
		}
			
	}
	
	
	
	public void nuevaFlota() {
		flotaActual = creadorFlotas.crearFlota(administradorNivel.getNivelActual()+3);
	}
	
	
	public void simular() throws JuegoPerdidoException, JuegoGanadoException {
		 
		
		
		//si no hay enemigos manda una nueva flota
		if (!flotaActual.tieneTanques())
			nuevaFlota();
	
		//si pasaron X ciclos crea un nuevo item
		contadorDeCiclos += 1;
		if (contadorDeCiclos > administradorNivel.getNivelActual()*100) {
			creadorItems.crearItem();
			contadorDeCiclos = 0;
		}
		
		//actualiza los objetos en el tiempo
		territorio.actualizar();
		
		//verifica el estado del juego
		checkearEstado();
		
	}
	
	
	public void checkearEstado() throws JuegoPerdidoException, JuegoGanadoException {
		if (!jugador.estaVivo() || !base.estaVivo())
			throw new JuegoPerdidoException();
		
		if (jugador.getPuntos() >= administradorNivel.getNivelActual() * 200)
			subirNivel();
	}

	public void addObservadorJuego(ObservadorJuego obs) {
		territorio.addObservadorJuego(obs);		
	}	

	public Base getBase() {
		return base;
	}
	
	public void pausar(){
		 if(!pausa)
			 pausa=true;
		 else
			 pausa=false;
			 
	}
	
	public boolean estaPausado(){
		return pausa;
	}
	public void enPausa(boolean pause){
		pausa=pause;
	}
	
	public void setJugador(AlgoTank algotank){
		
		jugador=algotank;
	}
	
	public void setBase(Base unaBase){
		base=unaBase;
	}

	public void setTerritorio(Territorio territorio) {
		this.territorio = territorio;
		
	}

	public CreadorDeFlotas getCreadorDeFlotas() {
		return this.creadorFlotas;
	}
	
	public CreadorDeItems getCreadorDeItems() {
		return this.creadorItems;
	}

	public void setCreadorDeFlotas(CreadorDeFlotas creadorDeFlotas) {
		this.creadorFlotas = creadorDeFlotas;
	}
	
	public void setCreadorDeItems(CreadorDeItems creadorDeItems) {
		this.creadorItems = creadorDeItems;
	}
	
	public Flota getFlota() {
		return this.flotaActual;
	}
	
	public void setFlota(Flota flota) {
		this.flotaActual = flota ;
	}
}
